'''
本机器人用于创建教师预约课表，减少教师在预约课程上的交流时间
功能：
1、教师创建教师课表，如可预约时间段，单次课程时间段
2、学生预约时间段，如初步预约，定金预约
3、教师确认预约时间段，等待上课
4、教师分享课表，展示可预约时间
'''
import logging,sqlite3
from datetime import datetime, timedelta
from telegram import Update
from collections import deque
from telegram.constants import ParseMode  # v20.0+ 版本
from telegram.ext import Application, CommandHandler, MessageHandler, filters, CallbackContext,CallbackQueryHandler
from buttons import cancelOneButton,studentCourse,createStudentCourse,createTimeIntervalsKeyboard,time_intervals,istoCreateCourse,createMarkupConfirmOne
from tools import genDate,modifyStrIndex
defaultMuban='000000000000111111111111'
class TelegramBot:
    def __init__(self, token: str):
        self.token = token
        self.botName='yuyuekecheng_bot'
        self.application = Application.builder().token(token).build()
         # 配置日志
        logging.basicConfig(level=logging.WARNING)
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.WARNING)  # Allow all messages through to handlers
        #数据库
        self.conn=sqlite3.connect('bookCourse/yuyue.db')
        self.cursor=self.conn.cursor()  #两行不可以写成一行

        now,tomorrow,Date0,Date1=genDate()
        #老师
        self.teachersDict={}
        query = "SELECT * FROM teacher ;"
        for row in self.cursor.execute(query).fetchall():
            nickname,muban,day0,day1,hideRest,date0,date1,chatID=row
            self.teachersDict[nickname]={'toDeleteMsgDeque':deque(),'chatID':chatID,'muban':muban,'day0':day0,'day1':day1,'hideRest':hideRest,'date0':date0,'date1':date1,'nickname':nickname,'displayToday':0,'bookedCourseList':[]}
        self.defaultTeacher={'toDeleteMsgDeque':deque(),'chatID':0,'muban':defaultMuban,'day0':defaultMuban,'day1':defaultMuban,'hideRest':0,'date0':Date0,'date1':Date1,'nickname':None,'displayToday':0,'bookedCourseList':[]}
        self.curTeacher=dict(self.defaultTeacher)
        #学生
        self.defaultStudent={'thisTeacher':None,'hideRest':0,'nickname':None,'displayToday':0,'toDeleteMsgDeque':deque()}
        self.studentsDict={}
        query = "SELECT * FROM student ;"
        for row in self.cursor.execute(query).fetchall():
            nickname,fullname,chatID,thisTeacher=row
            self.studentsDict[nickname]={'thisTeacher':thisTeacher,'toDeleteMsgDeque':deque(),'chatID':chatID,'fullname':fullname,'hideRest':0,'nickname':nickname,'displayToday':0}
        self.curStudent=dict(self.defaultStudent)
        #读取课程
        query = "SELECT * FROM bookedCourse WHERE date IN (?,?);"
        for row in self.cursor.execute(query,[Date0,Date1]).fetchall():
            teacher,student,date,peroidIndex,status,msg,id=row
            self.teachersDict[teacher]['bookedCourseList'].append({
                'teacher':teacher,
                'student':student,
                'date':date,
                'peroidIndex':peroidIndex,
                'status':status,#0学生已申请但老师未确认  1学生已申请且老师已确认
                'msg':msg,  #备注   接受用户文本输入，复杂，暂未开发
                'id':id
            })
        #删除信息  self.curTeacher['displayToday']==0
        self.toDeleteMsgDeque=deque()
    # 添加错误日志记录
    def error_handler(self, update: object, context: CallbackContext) -> None:
        try:
            self.logger.error('处理更新时发生错误', exc_info=context.error)
        except UnicodeEncodeError:
            self.logger.error('处理更新时发生错误 (编码问题)', exc_info=context.error)

    async def handle_message(self, update: Update, context: CallbackContext) -> None:
        # process_teacher_text(update.message.text)
        if update.effective_chat.type != 'group' and update.effective_chat.type != 'supergroup':
            #私聊信息
            text = update.message.text
            print(text)
    
    def updateCourse(self,nickname):
        now,tomorrow,date0,date1=genDate()
        self.curTeacher=self.teachersDict[nickname]
        if self.curTeacher['day1']==defaultMuban:self.curTeacher['day1']=self.curTeacher['muban']
        if now.strftime("%m-%d")!=self.curTeacher['date0']:
            self.curTeacher['date0']=date0
            self.curTeacher['day1']=self.curTeacher['muban']
            self.curTeacher['date1']=date1
            if date0==self.curTeacher['date1']:
                self.curTeacher['day0']=self.curTeacher['day1']
            else:#今天的日期，既不是date0,也不是date0的第二天
                self.curTeacher['day0']=self.curTeacher['muban']
            self.curTeacher['bookedCourseList']=list(filter(lambda T:T['date'] in (date0,date1),self.curTeacher['bookedCourseList']))
            #存储
            fields=('date0','date1','day0','day1')
            set_clause = ", ".join([f"{field} = ?" for field in fields])
            values = [date0,date1,self.curTeacher['day0'],self.curTeacher['day1'],nickname]  # 参数值列表
            query = f"UPDATE teacher SET {set_clause} WHERE nickname = ?"
            self.cursor.execute(query, values)
            self.conn.commit()
        return self.curTeacher
    async def start(self, update, context):
        '''机器人私聊窗口'''
        now = datetime.now()
        tomorrow=now+timedelta(days=1)
        date0=now.strftime("%m-%d")
        date1=tomorrow.strftime("%m-%d")
        chatID=update.message.chat.id
        args = context.args  # 获取命令后的参数列表   update.message.from_user.username, 
        if args:
            # 如果有参数，将第一个参数作为用户ID或其他标识符
            #判断链接中的username与当前访问的username是否相同
            #相同，则进入课表管理模式，不相同则进入预约模式
            user_id = args[0]
            #点击链接进入机器人，点击者ID与链接参数中的课表所有者ID相同，教师进入
            if update.message.from_user.username==user_id:
                if update.message.from_user.username not in self.teachersDict:
                    #创建新老师
                    self.defaultTeacher['nickname']=update.message.from_user.username
                    self.teachersDict[update.message.from_user.username]=dict(self.defaultTeacher)
                    query = "INSERT INTO teacher (nickname,date0,date1,chatID) VALUES (?,?,?,?);"
                    self.cursor.execute(query,[update.message.from_user.username,date0,date1],chatID)
                    self.conn.commit()
                    self.curTeacher=self.teachersDict[update.message.from_user.username]
                else:#表里存在老师  检查信息是否最新 
                    self.curTeacher=self.updateCourse(update.message.from_user.username)
                
                fullname=update.message.from_user.first_name+update.message.from_user.last_name
                message=await update.message.reply_text(
                    f"{fullname}老师  欢迎回来！您的课表如下",
                    disable_web_page_preview=True,
                    disable_notification=True,
                    reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
                )
                await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            else:#不同，则为学生进入课表
                try:
                    self.curTeacher=self.teachersDict[user_id]
                except:
                    message=await update.message.reply_text(f"{user_id} 没有此老师的课表")
                studentNickname=update.message.from_user.username
                studentFullname=update.message.from_user.first_name+update.message.from_user.last_name
                if studentNickname not in self.studentsDict:
                    self.defaultStudent['nickname']=studentNickname
                    self.defaultStudent['fullname']=studentFullname
                    self.defaultStudent['chatID']=chatID  #thisTeacher
                    self.defaultStudent['thisTeacher']=user_id
                    self.studentsDict[studentNickname]=dict(self.defaultStudent)
                    query = "INSERT INTO student (nickname,fullname,chatID,thisTeacher) VALUES (?,?,?,?);"
                    self.cursor.execute(query,[studentNickname,studentFullname,chatID,user_id])
                    self.conn.commit()
                self.curStudent=self.studentsDict[studentNickname]
                if self.curTeacher['date0']!=date0:
                    if self.curTeacher['date1']!=date0:
                        message=await update.message.reply_text(f"@{user_id} 老师暂未更新课表，请联系老师本人",)
                        return
                    else:
                        self.curTeacher['day1']=self.curTeacher['muban']
                        self.curTeacher['day0']=self.curTeacher['day1'] if self.curTeacher['day1'] else self.curTeacher['muban']

                message = await update.message.reply_text(
                    text="@%s老师的课表如下："%self.curTeacher['nickname'],
                    disable_web_page_preview=True,
                    disable_notification=True,
                    reply_markup=createStudentCourse(self.curStudent,self.curTeacher)
                )
                await self.deleteOldMsg(message,self.curStudent['toDeleteMsgDeque'])
        else:#没有参数，初次进入本机器人
            # 查询是否有课表  
            nickname=update.message.from_user.username
            fullname=update.message.from_user.first_name+update.message.from_user.last_name
            #名单在学生列表中
            if nickname in self.studentsDict:
                sql="SELECT teacher FROM bookedCourse WHERE student = ? ORDER BY id DESC LIMIT 1"
                row=self.cursor.execute(sql,[nickname]).fetchone()
                if row:
                    print(row)
                    teacher,=row
                    message=await update.message.reply_text(
                        f"@{teacher} 老师的课表如下:",
                        disable_web_page_preview=True,
                        disable_notification=True,
                        reply_markup=createStudentCourse(self.studentsDict[nickname],self.teachersDict[teacher])
                    )
                    await self.deleteOldMsg(message,self.curStudent['toDeleteMsgDeque'])
                else:
                    message = await update.message.reply_text(
                        text="%s老师，欢迎使用课程预约系统，是否为您创建初始课表？"%fullname,
                        # parse_mode=ParseMode.HTML,
                        disable_web_page_preview=True,
                        disable_notification=True,
                        reply_markup=istoCreateCourse(nickname)
                    )
            #名单在教师列表中
            elif nickname in self.teachersDict:
                self.curTeacher=self.updateCourse(update.message.from_user.username)
                message = await update.message.reply_text(
                    text="%s老师，您的课表地址：https://t.me/%s?start=%s"%(fullname,self.botName,nickname),
                    disable_web_page_preview=True,
                    disable_notification=True,
                    reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
                )
                await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            else:#空 
                #询问是否创建课表 
                message = await update.message.reply_text(
                    text="%s老师，欢迎使用课程预约系统，是否为您创建初始课表？"%fullname,
                    # parse_mode=ParseMode.HTML,
                    disable_web_page_preview=True,
                    disable_notification=True,
                    reply_markup=istoCreateCourse(nickname)
                )
                #先展示课表再操作数据库，节省等待时间
                
    async def callback_handler(self,update, context):
        callback_query = update.callback_query
        nickname=callback_query.from_user.username
        
        if callback_query.data=='hideRest':#教师界面，休息时段的显示或隐藏
            self.curTeacher=self.updateCourse(nickname)
            self.curTeacher['hideRest']=1 if self.curTeacher['hideRest']==0 else 0
            message = await callback_query.message.reply_text(
                text="可点击显示/隐藏休息时段",
                # parse_mode=ParseMode.HTML,
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
            )
            await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            await callback_query.answer('显示/隐藏休息时段')
        elif 'hideRest_STD' in callback_query.data:#学生界面，休息时段的显示或隐藏
            self.curStudent=self.studentsDict[nickname]
            teacherName=callback_query.data.split('+')[0]
            self.curTeacher=self.updateCourse(teacherName)
            self.curStudent['hideRest']=1 if self.curStudent['hideRest']==0 else 0
            message = await callback_query.message.reply_text(
                text="可点击显示/隐藏休息时段",
                # parse_mode=ParseMode.HTML,
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=createStudentCourse(self.curStudent,self.curTeacher)
            )
            await self.deleteOldMsg(message,self.curStudent['toDeleteMsgDeque'])
            await callback_query.answer('显示/隐藏休息时段')
        elif callback_query.data=='refresh':#教师界面，课表刷新
            self.curTeacher=self.updateCourse(nickname)
            message = await callback_query.message.reply_text(
                text="已刷新",
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
            )
            await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            await callback_query.answer('已刷新')
        elif 'STD_refresh' in callback_query.data:#学生界面，课表刷新
            teacherName=callback_query.data.split('+')[0]
            self.curTeacher=self.updateCourse(teacherName)
            self.curStudent=self.studentsDict[nickname]
            message = await callback_query.message.reply_text(
                text="已刷新",
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=createStudentCourse(self.curStudent,self.curTeacher)
            )
            await self.deleteOldMsg(message,self.curStudent['toDeleteMsgDeque'])
            await callback_query.answer('已刷新')
        elif 'STD_mycourse' in callback_query.data:#学生界面，学生自己的预约
            self.curStudent=self.studentsDict[nickname]
            now,tomorrow,date0,date1=genDate()
            sql='''SELECT * FROM bookedCourse WHERE date IN (?, ?) AND status IN (0,1)AND student=?;'''
            res=self.cursor.execute(sql,[date0,date1,nickname]).fetchall()
            if len(res)>0:
                message = await callback_query.message.reply_text(
                    text='您的预约如下：',
                    disable_web_page_preview=True,
                    disable_notification=True,
                    reply_markup=studentCourse(self.curStudent,res)
                )
                await self.deleteOldMsg(message,self.curStudent['toDeleteMsgDeque'])
            else:
                message = await callback_query.message.reply_text(text='您暂时没有预约')
            await callback_query.answer('您的预约')
        elif 'today/tomorrow' in callback_query.data:#分支处理，教师或学生界面，今、明两天课表切换
            _,user,teacherName=tuple(callback_query.data.split('+'))
            if user == 'teacher':
                self.curTeacher=self.updateCourse(teacherName)
                if self.curTeacher['displayToday']==0:
                    self.curTeacher['displayToday']=1
                    messageText="明天的课表"
                else:
                    self.curTeacher['displayToday']=0
                    messageText="今天的课表"
                reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
            else:
                self.curStudent=self.studentsDict[nickname]
                self.curTeacher=self.updateCourse(teacherName)
                if self.curStudent['displayToday']==0:
                    self.curStudent['displayToday']=1
                    messageText="@%s 老师明天的课表"%self.curTeacher['nickname']
                else:
                    self.curStudent['displayToday']=0
                    messageText="@%s 老师今天的课表"%self.curTeacher['nickname']
                reply_markup=createStudentCourse(self.curStudent,self.curTeacher)
            
            message = await callback_query.message.reply_text(
                text=messageText,
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=reply_markup
            )
            if user == 'teacher':
                await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            else:
                await self.deleteOldMsg(message,self.curStudent['toDeleteMsgDeque'])
            await callback_query.answer('已切换')
        elif callback_query.data=='CourseUrl':#教师界面，取得课表地址
            self.curTeacher=self.updateCourse(nickname)
            message = await callback_query.message.reply_text(
                text="https://t.me/%s?start=%s"%(self.botName,self.curTeacher['nickname'])
            )
            await callback_query.answer('他人可从课表地址申请课程')
        elif callback_query.data=='allRest':#教师界面，当前日期课表，除已确认预约外，全部设置为休息，通知已预约未确认学生：取消课程
            self.curTeacher=self.updateCourse(nickname)
            now,tomorrow,date0,date1=genDate()
            if self.curTeacher['displayToday']==0:
                thisDayStr='day0'
                date=date0
            else:
                thisDayStr='day1'
                date=date1
            course24=self.curTeacher[thisDayStr]
            newcourse24List=[]
            for peroidIndex,code in enumerate(course24):
                if code in ['0','1']:
                    newcourse24List.append('0')
                elif code=='2':  #有预约未确认  拒绝已申请学生
                    for item in self.curTeacher['bookedCourseList']:
                        if item['date']==date and peroidIndex==item['peroidIndex']:
                            sql="UPDATE bookedCourse SET status = 2 WHERE id = ?"
                            self.cursor.execute(sql,[item['id']])
                            item['status']=2
                            msg='抱歉，该时段被设置为休息，请申请其他时段\n老师：@%s\n日期：%s\n时段：%s'%(item['teacher'],date,time_intervals[peroidIndex])
                            await self.application.bot.send_message(chat_id=self.studentsDict[item['student']]['chatID'],text=msg,disable_notification=True)
                    
                    newcourse24List.append('0')
                else:
                    newcourse24List.append(code)
            self.curTeacher[thisDayStr]=''.join(newcourse24List)
            sql="UPDATE teacher SET %s = ? WHERE nickname = ?"%thisDayStr
            self.cursor.execute(sql,[self.curTeacher[thisDayStr],self.curTeacher['nickname']])
            self.conn.commit()
            message = await callback_query.message.reply_text(
                text="%s课程已被设置为全休，已通知所有预约学生，可点击状态，再次改为开放预约"%(date),
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
            )
            await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            await callback_query.answer('无预约时段设置为全休，已预约课程需与学生沟通')
        elif callback_query.data=='saveSetting':#教师界面，保存课表设置，如每天休息时段
            self.curTeacher=self.updateCourse(nickname)
            template=self.curTeacher['day0'] if self.curTeacher['displayToday']==0 else self.curTeacher['day1']
            muban=[]
            for code in template:
                if code=='0':
                    muban.append('0')
                else:
                    muban.append('1')
            muban=''.join(muban)
            self.curTeacher['muban']=muban
            sql="UPDATE teacher SET muban = ? WHERE nickname = ?"
            self.cursor.execute(sql,[muban,self.curTeacher['nickname']])
            self.conn.commit()
            await callback_query.answer('已保存课表模板')
        elif 'courseStatus' in callback_query.data:#教师界面，课程状态，不同状态点击时，出发不同响应
            self.curTeacher=self.updateCourse(nickname)
            tempData=callback_query.data.split("+")[0]
            statusCode,dateStr,hourNum=tuple(tempData.split(' '))
            statusCode=int(statusCode)
            hourNum=int(hourNum)
            # 0代表休息  1代表开放预约 2代表有申请未确认 3代表已确认申请 4代表预约已过期
            if statusCode==0 or statusCode==1:
                if self.curTeacher['date0']==dateStr:
                    courseStatusCode=self.curTeacher['day0'][hourNum]
                    thisDayCourse='day0'
                else:
                    courseStatusCode=self.curTeacher['day1'][hourNum]
                    thisDayCourse='day1'
                if courseStatusCode=='0':
                    courseStatusCode_new='1'
                    newStatustext='开放预约'
                elif courseStatusCode=='1':
                    courseStatusCode_new='0'
                    newStatustext='休息'

                self.curTeacher[thisDayCourse]=modifyStrIndex(self.curTeacher[thisDayCourse],hourNum,courseStatusCode_new)
                sql="UPDATE teacher SET %s = ? WHERE nickname = ?"%thisDayCourse#数据库
                self.cursor.execute(sql,[self.curTeacher[thisDayCourse],self.curTeacher['nickname']])
                self.conn.commit()
                self.teachersDict[nickname]=dict(self.curTeacher)
                message=await callback_query.message.reply_text(
                    text="%s %s时段已切换为：%s"%(dateStr,time_intervals[hourNum],newStatustext),
                    disable_web_page_preview=True,
                    disable_notification=True,
                    reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
                )
                await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
                await callback_query.answer('已切换%s'%newStatustext)
            elif statusCode==2:#多个预约中，确认一个
                studentAptList=[]
                for item in self.curTeacher['bookedCourseList']:
                    if all([
                        dateStr==item['date'],
                        hourNum==int(item['peroidIndex']),
                        item['status']==0  #申请未确认
                    ]):
                        studentAptList.append({
                            'nickname':item['student'],
                            'fullname':self.studentsDict[item['student']]['fullname']
                        })

                message=await callback_query.message.reply_text(
                    text="%s %s时段有%d人预约,选择其种一个:"%(dateStr,time_intervals[hourNum],len(studentAptList)),
                    disable_web_page_preview=True,
                    disable_notification=False,
                    reply_markup=createMarkupConfirmOne(studentAptList,dateStr,hourNum)
                )
                await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            elif statusCode==3:
                self.curTeacher=self.teachersDict[nickname]
                tempList=list(filter(lambda item:item['teacher']==nickname and item['date']==dateStr and item['peroidIndex']==hourNum and item['status']==1,self.curTeacher['bookedCourseList']))
                if len(tempList)==1:
                     item=tempList[0]
                     studentNickname=tempList[0]['student']
                     studentFullname=self.studentsDict[studentNickname]['fullname']
                     message = await callback_query.message.reply_text(
                        text='学生ID：@%s\n昵称：%s\n日期：%s\n时段：%s'%(studentNickname,studentFullname,dateStr,time_intervals[hourNum]),
                        disable_web_page_preview=True,
                        disable_notification=False,
                        reply_markup=cancelOneButton(item['id'])
                    )
                     await callback_query.answer(text="ok")
                else:
                    await callback_query.answer(text="数据异常，联系管理员",show_alert=True)
        elif 'courseSTD_status' in callback_query.data:#学生界面，课程状态，暂无点击响应
            await callback_query.answer('不可点击',show_alert=True)
        elif 'moreSetting' in callback_query.data:#教师界面，对某个时段单独设置，暂未开发

            await callback_query.answer('暂未开发')
        elif 'createNewCourse' in callback_query.data:#教师界面，初次进入时，创建初始刻表
            nickname=callback_query.data.split('+')[0]
            fullname=callback_query.from_user.first_name+callback_query.from_user.last_name
            now,tomorrow,date0,date1=genDate()
            self.defaultTeacher['nickname']=nickname
            self.defaultTeacher['date0']=date0
            self.defaultTeacher['date1']=date1
            self.teachersDict[nickname]=dict(self.defaultTeacher)
            self.curTeacher=self.teachersDict[nickname]
            message = await callback_query.message.reply_text(
                text="%s老师，您的课表地址：https://t.me/%s?start=%s"%(fullname,self.botName,nickname),
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
            )
            await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            
            query = "INSERT INTO teacher (nickname,date0,date1,chatID) VALUES (?,?,?,?);"
            self.cursor.execute(query,[nickname,date0,date1,callback_query.message.chat.id])
            self.conn.commit()
            await callback_query.answer('他人可从课表地址申请课程')
        elif 'appoint' in callback_query.data:#学生界面，预约时段
            formatted_date,timeIndex,statusCode,teacherNickname=tuple(callback_query.data.split('+')[0].split(' '))
            timeIndex=int(timeIndex)
            statusCode=int(statusCode)
            if statusCode==0:#0代表休息  1代表开放预约 2代表有申请未确认 3代表已确认申请 4代表预约已过期
                await callback_query.answer(
                    text="休息，不可预约",        # 可选：显示给用户的消息
                    show_alert=True,       # 可选：是否以弹窗形式显示消息
                )
            elif statusCode==1 or statusCode==2:
                self.curTeacher=self.teachersDict[teacherNickname]
                for item in self.curTeacher['bookedCourseList']:
                    if all([
                        teacherNickname==item['teacher'],
                        callback_query.from_user.username==item['student'],
                        formatted_date==item['date'],
                        timeIndex==item['peroidIndex']
                    ]):
                        await callback_query.answer(text="已预约,请勿重复预约",show_alert=True)
                        return
                
                #修改时段状态
                updateFlag=False
                if formatted_date==self.curTeacher['date0']:
                    tempList=list(self.curTeacher['day0'])
                    thisDayCourse='day0'
                    if tempList[timeIndex]=='1':  #无预约状态1，变为有预约状态2
                        tempList[timeIndex]='2'
                        updateFlag=True
                        
                elif formatted_date==self.curTeacher['date1']:
                    tempList=list(self.curTeacher['day1'])
                    thisDayCourse='day1'
                    if tempList[timeIndex]=='1':
                        tempList[timeIndex]='2'
                        updateFlag=True
                else:
                    await callback_query.answer(text="异常参数",show_alert=True)
                    return

                if updateFlag:  #如果本来就有预约，则不修改
                    self.curTeacher[thisDayCourse]=''.join(tempList)
                    sql="UPDATE teacher SET %s = ? WHERE nickname = ?"%thisDayCourse#数据库
                    self.cursor.execute(sql,[self.curTeacher[thisDayCourse],self.curTeacher['nickname']])
                #数据库操作
                query = "INSERT INTO bookedCourse (teacher,student,date,peroidIndex,status,msg) VALUES (?,?,?,?,?,?);"
                self.cursor.execute(query,[teacherNickname,callback_query.from_user.username,formatted_date,timeIndex,0,''])
                self.conn.commit()
                self.curTeacher['bookedCourseList'].append({
                    'teacher':teacherNickname,
                    'student':callback_query.from_user.username,
                    'date':formatted_date,
                    'peroidIndex':timeIndex,
                    'status':0,#0学生已申请但老师未确认  1学生已申请且老师已确认
                    'id':self.cursor.lastrowid,  #备注   接受用户文本输入，复杂，暂未开发
                    'msg':''
                })
                message = await callback_query.message.reply_text(
                    text='''您的预约：\n老师：@%s\n日期：%s\n时段：%s\n已通知老师，请等待确认。\n给老师留言，通过概率更高，可给老师私发口令。
                        '''%(teacherNickname,formatted_date,time_intervals[timeIndex]),
                )
                forTeacherMsgText='''您有新的预约：\n日期：%s\n时段：%s\n学生：@%s
                        '''%(formatted_date,time_intervals[timeIndex],callback_query.from_user.username)

                await self.application.bot.send_message(chat_id=self.curTeacher['chatID'],text=forTeacherMsgText,disable_notification=False)
            elif statusCode==3:
                await callback_query.answer(text="不可再预约",show_alert=True)
            elif statusCode==4:
                await callback_query.answer(text="该时段已过期",show_alert=True)
        elif 'ConfirmOne' in callback_query.data:#教师界面，在某个时段下的所有预约中，确认一个预约，并拒绝其他
            date,peroidIndex,stu=tuple(callback_query.data.split('+')[0].split())
            peroidIndex=int(peroidIndex)
            now,tomorrow,date0,date1=genDate()
            self.curTeacher=self.teachersDict[nickname]
            for item in self.curTeacher['bookedCourseList']:
                if item['date']==date and int(peroidIndex)==item['peroidIndex'] and item['status']==0:
                    chatID=self.studentsDict[item['student']]['chatID']
                    if item['student']==stu:#发送通过申请或拒绝申请的信息
                        msg='恭喜！您的预约已通过，请按时到达。\n老师：@%s\n日期：%s\n时段：%s'%(nickname,date,time_intervals[peroidIndex])
                        message = await callback_query.message.reply_text(
                            text='已确认与%s同学的预约，机器人已通知：\n学生：@%s\n日期：%s\n时段：%s'%(self.studentsDict[stu]['fullname'],stu,date,time_intervals[peroidIndex])
                        )
                        #数据库
                        thisDayCourse='day0' if date==date0 else 'day1'
                        self.curTeacher[thisDayCourse]=modifyStrIndex(self.curTeacher[thisDayCourse],peroidIndex,3)
                        item['status']=1
                        sql="UPDATE teacher SET %s = ? WHERE nickname = ?"%thisDayCourse
                        self.cursor.execute(sql,[self.curTeacher[thisDayCourse],self.curTeacher['nickname']])
                        sql="UPDATE bookedCourse SET status = 1 WHERE id = ?"
                        self.cursor.execute(sql,[item['id']])
                        await self.application.bot.send_message(chat_id=chatID,text=msg,disable_notification=True)
                    else:
                        sql="UPDATE bookedCourse SET status = 2 WHERE id = ?"
                        self.cursor.execute(sql,[item['id']])
                        item['status']=2
                        msg='抱歉，您的预约被拒绝，请重新申请其他时段\n老师：@%s\n日期：%s\n时段：%s'%(nickname,date,time_intervals[peroidIndex])
                        await self.application.bot.send_message(chat_id=chatID,text=msg,disable_notification=True)
                    
            self.conn.commit()
            message = await callback_query.message.reply_text(
                text="状态已刷新",
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
            )
            await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            await callback_query.answer('已确认申请，请按时上课')
        elif 'Reject' in callback_query.data:#教师界面，在某个时段下的所有预约中，拒绝一个预约，不影响其他预约
            date,peroidIndex,stu=tuple(callback_query.data.split('+')[0].split())
            peroidIndex=int(peroidIndex)
            now,tomorrow,date0,date1=genDate()
            self.curTeacher=self.teachersDict[nickname]
            for item in self.curTeacher['bookedCourseList']:
                if item['date']==date and int(peroidIndex)==item['peroidIndex'] and stu==item['student'] and item['status']==0:
                    chatID=self.studentsDict[item['student']]['chatID']
                    sql="UPDATE bookedCourse SET status = 2 WHERE id = ?"
                    self.cursor.execute(sql,[item['id']])
                    item['status']=2
                    msg='抱歉，您的预约被拒绝，请重新申请其他时段\n老师：@%s\n日期：%s\n时段：%s'%(nickname,date,time_intervals[peroidIndex])
                    await self.application.bot.send_message(chat_id=chatID,text=msg,disable_notification=True)
                    break
            self.conn.commit()
            message = await callback_query.message.reply_text(
                text="状态已刷新",
                disable_web_page_preview=True,
                disable_notification=True,
                reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
            )
            await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
            await callback_query.answer('拒绝一个申请')
        elif 'stuCancelOne' in callback_query.data:#学生界面,学生取消自己的预约
            teacher,student,date,peroidIndex,courseID=tuple(callback_query.data.split('+')[0].split(' '))
            peroidIndex=int(peroidIndex)
            self.curTeacher=self.teachersDict[teacher]
            now,tomorrow,date0,date1=genDate()
            tempList=list(filter(lambda item:item['student']==student and item['date']==date and item['peroidIndex']==int(peroidIndex),self.curTeacher['bookedCourseList']))
            if len(tempList)==1:
                item=tempList[0]
                if item['status']==1:#已确认的预约被取消，要通知老师
                    forTeacherMsgText='一个已确认预约被取消：\n日期：%s\n时段：%s\n学生：@%s'%(date,time_intervals[peroidIndex],student)
                    await self.application.bot.send_message(chat_id=self.curTeacher['chatID'],text=forTeacherMsgText,disable_notification=True)
                item['status']=3
                sql_1='UPDATE bookedCourse SET status = 3 WHERE id = ?;'
                self.cursor.execute(sql_1,[courseID])
                thisDayStr=''
                if date==date0:
                    thisDayStr='day0'
                elif date==date1:
                    thisDayStr='day1'
                else:
                    await callback_query.answer(text="数据异常1",show_alert=True)
                if len(thisDayStr):
                    self.curTeacher[thisDayStr]=modifyStrIndex(self.curTeacher[thisDayStr],peroidIndex,1)
                    sql_2='UPDATE teacher SET %s = ? WHERE nickname = ?;'%thisDayStr
                    self.cursor.execute(sql_2,[self.curTeacher[thisDayStr],self.curTeacher['nickname']])
                    self.conn.commit()
                    message = await callback_query.message.reply_text(
                        text='取消成功,机器人已通知老师，@%s'%self.curTeacher['nickname']
                    )
            else:
                await callback_query.answer(text="数据异常2",show_alert=True)
        elif 'teaCancelChecked' in callback_query.data:#教师界面,取消已经确认的预约
            courseID=int(callback_query.data.split('+')[0])
            now,tomorrow,date0,date1=genDate()
            self.curTeacher=self.teachersDict[nickname]
            tempList=list(filter(lambda item:item['id']==courseID,self.curTeacher['bookedCourseList']))
            if len(tempList)==1:
                item=tempList[0]
                item['status']=2
                sql='UPDATE bookedCourse SET status = 2 WHERE id = ?;'
                self.cursor.execute(sql,[courseID])
                #修改教师课表状态为可预约
                timeIndex=item['peroidIndex']
                updateFlag=False
                if item['date']==self.curTeacher['date0']:
                    tempList=list(self.curTeacher['day0'])
                    thisDayCourse='day0'
                    tempList[timeIndex]='1' #无预约状态1，变为有预约状态2
                    updateFlag=True
                elif item['date']==self.curTeacher['date1']:
                    tempList=list(self.curTeacher['day1'])
                    thisDayCourse='day1'
                    tempList[timeIndex]='1'
                    updateFlag=True
                else:
                    await callback_query.answer(text="课表过期，刷新后重试",show_alert=True)
                if updateFlag:
                    self.curTeacher[thisDayCourse]=''.join(tempList)
                    sql="UPDATE teacher SET %s = ? WHERE nickname = ?"%thisDayCourse#数据库
                    self.cursor.execute(sql,[self.curTeacher[thisDayCourse],self.curTeacher['nickname']])
                    self.conn.commit()
                    # sql='SELECT student.chatID FROM bookedCourse WHERE id=?;'
                    # self.cursor.execute(sql,[courseID])
                    stuChatID=self.studentsDict[item['student']]['chatID']
                    forStuMsgText='您的预约已被取消\n老师ID：@%s\n日期：%s\n时段：%s'%(nickname,item['date'],time_intervals[timeIndex])
                    await self.application.bot.send_message(chat_id=stuChatID,text=forStuMsgText,disable_notification=True)
                    message = await callback_query.message.reply_text(
                        text='取消成功,机器人已通知学生，@%s'%item['student'],
                        disable_web_page_preview=True,
                        disable_notification=True,
                        reply_markup=createTimeIntervalsKeyboard(self.curTeacher)
                    )
                    await self.deleteOldMsg(message,self.curTeacher['toDeleteMsgDeque'])
                    await callback_query.answer(text="取消成功",show_alert=True,cache_time=3)
            else:
                await callback_query.answer(text="数据异常，联系管理员",show_alert=True)
        else:
            await callback_query.answer(callback_query.data, cache_time=3)
        
        
    async def deleteOldMsg(self,message,targetDeque):
        now = datetime.now()
        toDeieteItem={"timeStamp":now.timestamp(),"chat_id":message.chat_id,"message_id":message.message_id,}
        targetDeque.append(toDeieteItem)
        #加入新的 删除旧的
        if len(targetDeque)>3 or now.timestamp()-targetDeque[0]['timeStamp']>3600:
            item=targetDeque.popleft()
            try:
                await self.application.bot.delete_message(chat_id=item['chat_id'],message_id=item['message_id'])
            except Exception as e:
                self.logger.error(f"删除消息时出错: {e}")

    def run(self) -> None:
        # 注册消息处理器（处理所有文本消息）
        self.application.add_handler(MessageHandler(filters.ALL & ~filters.COMMAND, self.handle_message))   
        #机器人底部开始按钮
        self.application.add_handler(CommandHandler("start", self.start)) 
        #按钮点击回调函数
        self.application.add_handler(CallbackQueryHandler(self.callback_handler))   
        # 添加错误处理器
        self.application.add_error_handler(self.error_handler)
        # 启动机器人
        print("机器人启动中...")
        try:
            self.application.run_polling()
        except KeyboardInterrupt:
            self.logger.info("接收到终止信号，正在优雅关闭...")
        except Exception as e:
            self.logger.error(f"机器人运行出错: {e}")
        finally:
            #新数据入库，过期数据丢弃
            # now = datetime.now()
            # tomorrow=now+timedelta(days=1)
            # date0=now.strftime("%m-%d")
            # date1=tomorrow.strftime("%m-%d")
            # for nickname,item in self.studentsDict.items():
            #     #UPDATE teacher SET %s = ? WHERE nickname = ?
            #     query = "INSERT INTO student (nickname,) VALUES (?);"
            #     self.cursor.execute(query,[nickname])
            # for nickname,item in self.teachersDict.items():
            #     query = "INSERT INTO teacher (nickname,date0,date1,day0,day1,muban,hideRest) VALUES (?,?,?,?,?,?,?);"
            #     self.cursor.execute(query,[nickname,item['date0'],item['date1'],item['day0'],item['day1'],item['muban'],item['hideRest']])
            #     for bookedCourse in item['bookedCourseList']:
            #         if bookedCourse['date']<date0:continue  #过期数据丢弃
            #         if bookedCourse['date']==date0 and now.hour>bookedCourse['peroidIndex']:continue
            #         query = "INSERT INTO bookedCourse (teacher,student,date,peroidIndex,status,msg) VALUES (?,?,?,?,?,?);"
            #         self.cursor.execute(query,[bookedCourse['teacher'],bookedCourse['student'],bookedCourse['date'],bookedCourse['peroidIndex'],bookedCourse['status'],bookedCourse['msg']])


            self.conn.commit()
            self.logger.info("机器人已停止")

def main() -> None:
    bot = TelegramBot("7956170031:AAFq7VtImLvn2CER_V7grgapKqdPGnZv94M")
    bot.run()

if __name__ == '__main__':
    main()
